package li.kaeppe.travel.tracker.dao;

import java.util.List;

import li.kaeppe.travel.tracker.domain.User;
import li.kaeppe.travel.tracker.domain.UserRole;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.security.userdetails.UserDetails;
import org.springframework.security.userdetails.UserDetailsService;
import org.springframework.security.userdetails.UsernameNotFoundException;
import org.springframework.transaction.annotation.Transactional;

@Transactional
public class HibernateUserDaoImpl implements UserDao, UserDetailsService {

	/* **************************************************** */
	/* CONSTANTS */
	/* **************************************************** */

	private static final Log log = LogFactory.getLog(HibernateUserDaoImpl.class);
	
	/* **************************************************** */
	/* MEMBER FIELDS */
	/* **************************************************** */

	private SessionFactory sessionFactory;
	
	/* **************************************************** */
	/* CONSTRUCTOR */
	/* **************************************************** */

	/* **************************************************** */
	/* PUBLIC METHODS */
	/* **************************************************** */

	public UserDetails loadUserByUsername(String username)
			throws UsernameNotFoundException, DataAccessException {
		if(log.isDebugEnabled()) {
			log.debug("loadUserByUsername for user [" +
					  username + 
					  "]");
		}
		
		Query query = this.getSession().createQuery("from User u where u.username = :username");
		query.setString("username", username);
		return (User)query.uniqueResult();
	}
	
	public void deleteUser(User user) {
		this.getSession().delete(user);
	}

	public List<User> getAllUsers() {
		Query query = this.getSession().createQuery("from User");
		
		@SuppressWarnings("unchecked")
		List<User> users = query.list();
		return users;
	}

	public User saveUser(User user) {
		this.getSession().saveOrUpdate(user);
		return user;
	}

	
	public List<UserRole> getAllRoles() {
		Query query = this.getSession().createQuery("from UserRole");
		
		@SuppressWarnings("unchecked")
		List<UserRole> roles = query.list();
		
		return roles;
	}
	
	public UserRole getRoleById(long id) {
		Query query = this.getSession().createQuery("from UserRole r where r.id = :id");
		return (UserRole)query.setLong("id", id).uniqueResult();
	}
	
	/* **************************************************** */
	/* PROTECTED METHODS */
	/* **************************************************** */

	/* **************************************************** */
	/* PRIVATE METHODS */
	/* **************************************************** */

	private Session getSession() {
		return this.getSessionFactory().getCurrentSession();
	}
	
	/* **************************************************** */
	/* GETTERS AND SETTERS */
	/* **************************************************** */
	
	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}
	
}
